package version3.part2.Client.proxy;


import version3.part2.Client.retry.guavaRetry;
import version3.part2.Client.rpcClient.RpcClient;
import version3.part2.Client.rpcClient.impl.NettyRpcClient;
import version3.part2.Client.serviceCenter.ServiceCenter;
import version3.part2.Client.serviceCenter.ZKServiceCenter;
import version3.part2.common.Message.RpcRequest;
import version3.part2.common.Message.RpcResponse;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ClientProxy implements InvocationHandler {
    //传入参数service接口的class对象，反射封装成一个request
    private ServiceCenter serviceCenter;
    private RpcClient rpcClient;
//    public ClientProxy(String host,int port,int choose){
//        switch (choose){
//            case 0:
//                rpcClient=new NettyRpcClient(host,port);
//                break;
//            case 1:
//                rpcClient=new SimpleSocketRpcCilent(host,port);
//        }
//    }
    public ClientProxy() throws InterruptedException {
        this.serviceCenter=new ZKServiceCenter();
        this.rpcClient= new NettyRpcClient(serviceCenter);
    }
    //jdk动态代理，每一次代理对象调用方法，都会经过此方法增强（反射获取request对象，socket发送到服务端）
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //构建request
        RpcRequest request= RpcRequest.builder()
                .interfaceName(method.getDeclaringClass().getName())
                .methodName(method.getName())
                .params(args).paramsType(method.getParameterTypes()).build();
        //数据传输
        RpcResponse response = null;
        if(serviceCenter.isRetry(request.getInterfaceName())){
            //如果服务可重试，执行超时重试逻辑
            response = new guavaRetry().sendRequestWithRetry(request,rpcClient);
        }else {
            //如果服务不可重试，不执行超时重试逻辑
            response = rpcClient.sendRequest(request);
        }
        return response.getData();
    }
     public <T>T getProxy(Class<T> clazz){
        Object o = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, this);
        return (T)o;
    }
}
